﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Net;

namespace Lil_Chipper
{
    public partial class frmLCMain : Form
    {
        public readonly string LCDat   = Application.StartupPath + "\\LilChipper.dat";
        public StateData       State   = new StateData();

        public frmLCMain()
        {
            InitializeComponent();
        }

        private void ReadDat()
        {
            if ( File.Exists( LCDat ) == true )
            {
                try
                {
                    Stream          stream    = File.Open( LCDat, FileMode.Open );
                    BinaryFormatter formatter = new BinaryFormatter();

                    State = ( StateData ) formatter.Deserialize( stream );
                    stream.Close();
                }
                catch ( Exception ex )
                {
                    MessageBox.Show( "Error opening LilChipper.dat:\n\n" + ex.Message );
                }
            }
            else
            {
                return;
            }
        }

        private void WriteDat()
        {
            if ( File.Exists( LCDat ) == true )
            {
                try
                {
                    File.Delete( LCDat );
                }
                catch ( Exception ex )
                {
                    MessageBox.Show( "Error deleting old LilChipper.dat:\n\n" + ex.Message );
                }
            }

            try
            {
                Stream          stream    = File.Open( LCDat, FileMode.OpenOrCreate );
                BinaryFormatter formatter = new BinaryFormatter();

                formatter.Serialize( stream, State );
                stream.Close();
            }
            catch ( Exception ex )
            {
                MessageBox.Show( "Error writing new LilChipper.dat:\n\n" + ex.Message );
            }
        }

        private void frmLCMain_Load( object sender, EventArgs e )
        {
            if ( File.Exists( LCDat ) == true )
            {
                ReadDat();
                PopulateComboBox( 0 );
            }
            else
            {
                WriteDat();
            }
        }

        private void cmdSaveTo_Click( object sender, EventArgs e )
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.RootFolder          = Environment.SpecialFolder.MyDocuments;

            if ( fbd.ShowDialog() == DialogResult.OK )
            {
                txtSaveTo.Text = fbd.SelectedPath + "\\";
                UpdateEntry();
            }
        }

        private void UpdateEntry()
        {
            int StoryIdx = -1;

            for ( int i = 0; i < 0; i++ )
            {
                if ( State.Stories[i].ID == cboID.Text )
                {
                    StoryIdx = i;
                    break;
                }
                else
                {
                    continue;
                }
            }

            if ( StoryIdx == -1 )
            {
                return;
            }
            else
            {
                State.Stories[StoryIdx].ID       = cboID.Text;
                State.Stories[StoryIdx].Name     = txtName.Text;
                State.Stories[StoryIdx].SaveTo   = txtSaveTo.Text;
                State.Stories[StoryIdx].Chapters = Convert.ToInt32( numChaps.Value );
            }
        }

        private void numChaps_ValueChanged( object sender, EventArgs e )
        {
            UpdateEntry();
        }

        private void txtSaveTo_TextChanged( object sender, EventArgs e )
        {
            UpdateEntry();
        }

        private void txtName_TextChanged( object sender, EventArgs e )
        {
            UpdateEntry();
        }

        private void cboID_SelectedIndexChanged( object sender, EventArgs e )
        {
            Story sel = new Story();

            foreach ( Story story in State.Stories )
            {
                if ( story.ID == cboID.Text )
                {
                    sel = story;
                    break;
                }
                else
                {
                    continue;
                }
            }

            numChaps.Value = Convert.ToDecimal( sel.Chapters );
            txtSaveTo.Text = sel.SaveTo;
            txtName.Text   = sel.Name;
        }

        private void PopulateComboBox( int StartIdx )
        {
            cboID.Items.Clear();

            if ( State.Stories.Count > 0 )
            {
                foreach ( Story story in State.Stories )
                {
                    cboID.Items.Add( story.ID );
                }

                cboID.SelectedIndex = StartIdx;
                cboID_SelectedIndexChanged( this, EventArgs.Empty );
            }
        }

        private void cboID_KeyUp( object sender, KeyEventArgs e )
        {
            if ( e.KeyCode == Keys.Enter || e.KeyCode == Keys.Return )
            {
                if ( e.Control == true )
                {
                    Story temp = new Story();

                    temp.ID       = cboID.Text;
                    temp.Chapters = Convert.ToInt32( numChaps.Value );
                    temp.Name     = txtName.Text;
                    temp.SaveTo   = txtSaveTo.Text;

                    foreach ( Story story in State.Stories )
                    {
                        if ( story.ID == temp.ID )
                        {
                            return;
                        }
                        else
                        {
                            continue;
                        }
                    }

                    State.Stories.Add( temp );
                    PopulateComboBox( State.Stories.Count - 1 );
                }
            }
        }

        private void cboID_MouseHover( object sender, EventArgs e )
        {
            ttpTool.Show( "Ctrl + Enter/Return to add to list.", cboID );
        }

        private void txtName_MouseHover( object sender, EventArgs e )
        {
            ttpTool.Show( "The name used when saving a story to disk.", txtName );
        }

        private void txtSaveTo_MouseHover( object sender, EventArgs e )
        {
            ttpTool.Show( "The directory to which this story will be saved once processed.", txtSaveTo );
        }

        private void cmdBegin_MouseHover( object sender, EventArgs e )
        {
            ttpTool.Show( "Commence downloading and processing of the selected story.", cmdBegin );
        }

        private void frmLCMain_FormClosing( object sender, FormClosingEventArgs e )
        {
            WriteDat();
        }

        private void cmdBegin_Click( object sender, EventArgs e )
        {
            if ( String.IsNullOrEmpty( cboID.Text ) == true )
            {
                MessageBox.Show( "Can't download a story without an ID!" );
                return;
            }
            else if ( String.IsNullOrEmpty( txtSaveTo.Text ) == true || Directory.Exists( txtSaveTo.Text) == false )
            {
                MessageBox.Show( "No location has been selected for the story to be saved or the selected directory doesn't exist!" );
                return;
            }
            else if ( String.IsNullOrEmpty( txtName.Text ) == true )
            {
                MessageBox.Show( "Can't save a story without a name!" );
                return;
            }
            else
            {
                string StoryURL = "http://www.fanfiction.net/s/" + cboID.Text;

                for ( int i = 1; i <= ( int ) numChaps.Value; i++ )
                {
                    string ChapURL   = StoryURL + "/" + Convert.ToString( i );

                    ParseHTML( Download( ChapURL ), txtSaveTo.Text + txtName.Text + " Ch " + Convert.ToString( i ) + ".html" );
                }

                MessageBox.Show( "Story downloaded, parsed, and saved to: " + txtSaveTo.Text );
            }
        }

        public void ParseHTML( string Data, string SaveTo )
        {
            int          Begindex = Data.IndexOf( "<div class=\'storytext xcontrast_txt nocopy\' id=\'storytext\'>" );
            int          Endex    = Data.IndexOf( "</div>", Begindex ) + "</div>".Length;
            int          Length   = Endex - Begindex;
            StreamWriter Writer   = new StreamWriter( File.Open( SaveTo, FileMode.OpenOrCreate ) );

            Writer.Write( Data.Substring( Begindex, Length ) );
            Writer.Flush();
            Writer.Close();
        }

        public string Download( string URL )
        {
            try
            {
                using ( WebClient client = new WebClient() )
                {
                    Stream       data   = client.OpenRead( URL );
                    StreamReader reader = new StreamReader( data );
                    string       s      = reader.ReadToEnd();

                    data.Close();
                    reader.Close();

                    return s;
                }
            }
            catch ( Exception ex )
            {
                MessageBox.Show( "Error in Download():\n\n" + ex.Message );
                return null;
            }
        }
    }
}
